package util;
import java.util.ArrayList;
import java.util.List;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import test.Main;

import algorithm.Classification;
import algorithm.RADDACL_Cluster;
import algorithm.Region;
/**
 * Displays a 2-D representation of clusters. Clustered input is essentially a list of Classifications
 * 
 * @author Dan Avila
 *
 */
public class Visual extends JFrame implements MouseListener, Runnable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */
	private JPanel2D finalCluster;
	private JPanel2D preCluster;
	
	private static final int X = 0;
	private static final int Y = 1;
	
	private double pixelsize = 20;
	private final double offset = 50;
	
	private Vector<Double> scale = new Vector<Double>();
	protected Vector<Double> min = new Vector<Double>();
	protected Vector<Double> max = new Vector<Double>();
	
	protected List<Color> colors = new ArrayList<Color>(6);
	protected int currentColor = 0;
	
	protected JTabbedPane tabbedPane = new JTabbedPane();
	
	
	private Main main;
	
	//boolean pause = false;
	
	protected List<Classification> inputs;
	protected List<Classification> preclusterClasses;
	
	public Visual(Main main){
		this.main = main;
		
		
		colors.add(Color.gray);
		colors.add(Color.cyan);
		colors.add(Color.red);
		colors.add(Color.green);
		colors.add(Color.blue);
		colors.add(Color.orange);
		
		this.inputs = main.getFinalClusters();
		try {
			this.preclusterClasses = this.main.getPreClusters();
			
			for(Classification cl: this.preclusterClasses)
			{
				System.out.println(cl.toString());
			}
			
			
		} catch (InstantiationException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		}
		
		this.preCluster = new JPanel2D(this, this.preclusterClasses);
		this.finalCluster = new JPanel2D(this, inputs);
		
	    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    
		this.tabbedPane.addTab("Preclusters", this.preCluster);
		this.tabbedPane.addTab("FinalClusters", this.finalCluster);
		
		this.getContentPane().add(this.tabbedPane);
		
		this.setSize(700,700);
		this.setTitle("Right-Click to regenerate.");
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		this.tabbedPane.addMouseListener(this);
		this.establishBounds();
		
		new Thread(this).run();
	}

	private void establishBounds() 
	{
		
		for(int i = 0;i<inputs.size();i++)
		{
			for(Vector<Double> point:inputs.get(i))
			{
				int valindex = 0;
				for(Double pointval: point)
				{
					if(min.size() < point.size())
					{
						min.add(pointval);
						max.add(pointval);
					}
					else
					{
						if(min.get(valindex)>pointval)
						{
							min.set(valindex, pointval);
						}
						if(max.get(valindex)<pointval)
						{
							max.set(valindex, pointval);
						}
					}
					valindex++;
				}
			}
		}
		
		scale.add(
				(this.finalCluster.getWidth()-offset*2) / (max.get(X)-min.get(X))
				);	//x
		
		scale.add(
				(this.finalCluster.getHeight()-offset*2) / (max.get(Y)-min.get(Y))
				);	//y
	}
	
	public Ellipse2D.Double drawPoint(Component c, double x, double y){
		
		double realx = getX(x);
		double realy = getY(y);
		
		return new Ellipse2D.Double
		(
			realx,
			this.finalCluster.getHeight() - realy,
			pixelsize,
			pixelsize
		);
	}
	
	private double getY(double y)
	{
		y = y - min.get(Y);
		return offset + (y*scale.get(Y)) - pixelsize/2;
	}

	private double getX(double x) 
	{
		x = x - min.get(X);
		return offset + (x*scale.get(X)) - pixelsize/2;
	}

	@Override
	public void paint(Graphics g){
		super.paint(g);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		
		
	}

	@Override
	public void mousePressed(MouseEvent e) 
	{
		if(e.getButton() == MouseEvent.BUTTON3)
			this.main.reset();
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		
		
	}

	@Override
	public void run() {

	}

	public void reset(Main main) 
	{
		
		try {
			this.inputs = main.getFinalClusters();
			this.preclusterClasses = main.getPreClusters();
		} catch (InstantiationException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		}
		
		//this.setTitle("Right-Click to RESET.");
		
		this.establishBounds();
		
		this.preCluster.setList(this.preclusterClasses);
		this.finalCluster.setList(this.inputs);
		
		this.repaint();
	}
}

	class JPanel2D extends javax.swing.JPanel{
    	/**
		 * 
		 */
		private static final long serialVersionUID = 7494896669933735439L;
	    private Visual visual;
	    private List<Classification> list;
	    
		public JPanel2D(Visual v, List<Classification> list){
			super();
			this.list = list;
			this.visual = v;
			this.setBackground(Color.white);
		}
		
		public void setList(List<Classification> list)
		{
			this.list = list;
		}
		
	    public void paintComponent(Graphics g) {
	    	super.paintComponent(g);
	    	Graphics2D g2 = (Graphics2D)g;
 
	    	g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
	    	
	    	int count = 50;
	    	int interval = (255*3) / list.size();
	    	
	    	visual.currentColor = 0;
	    	
	    	for(Classification classification: list)
	    	{
	    		g2.setColor(visual.colors.get(visual.currentColor));
	    		visual.currentColor = (visual.currentColor + 1) % visual.colors.size();
	    		
		    	for(Vector<Double> input: classification)
		    	{
		    		g2.draw(visual.drawPoint(this, input.get(0), input.get(1)));
		    	}
		    	
		    	count+=interval;
	    	}
	    	
	    	/*g2.setPaint(Color.black);
	    	
	    	g2.draw(visual.drawPoint(this, visual.min.get(0), visual.min.get(1)));
	    	
	    	g2.draw(visual.drawPoint(this, visual.max.get(0), visual.max.get(1)));
	    	
	    	g2.draw(visual.drawPoint(this, visual.r.getCentroid().get(0), visual.r.getCentroid().get(1)));*/
    	}

		private Color getColor(int interval) {
			
			if(interval < 255)
				return new Color(interval, 0, 0);
			else if(interval>255 && interval < 255*2)
				return new Color(0, interval%255, 0);
			else if(interval >255*2)
				return new Color(0, 0, interval%255);
			return new Color(255, 255, 255);
		}
	}
